1   /*
2    * Written by Doug Lea with assistance from members of JCP JSR-166
3    * Expert Group and released to the public domain, as explained at
4    * http://creativecommons.org/publicdomain/zero/1.0/
5    */
6   
7   /*
8    * Source:
9    * http://gee.cs.oswego.edu/cgi-bin/viewcvs.cgi/jsr166/src/jsr166e/LongAdder.java?revision=1.17
10   */
11  
12  package com.google.common.cache;
13  
14  import com.google.common.annotations.GwtCompatible;
15  
16  import java.io.IOException;
17  import java.io.ObjectInputStream;
18  import java.io.ObjectOutputStream;
19  import java.io.Serializable;
20  import java.util.concurrent.atomic.AtomicLong;
21  
22  /**
23   * One or more variables that together maintain an initially zero
24   * {@code long} sum.  When updates (method {@link #add}) are contended
25   * across threads, the set of variables may grow dynamically to reduce
26   * contention. Method {@link #sum} (or, equivalently, {@link
27   * #longValue}) returns the current total combined across the
28   * variables maintaining the sum.
29   *
30   * <p>This class is usually preferable to {@link AtomicLong} when
31   * multiple threads update a common sum that is used for purposes such
32   * as collecting statistics, not for fine-grained synchronization
33   * control.  Under low update contention, the two classes have similar
34   * characteristics. But under high contention, expected throughput of
35   * this class is significantly higher, at the expense of higher space
36   * consumption.
37   *
38   * <p>This class extends {@link Number}, but does <em>not</em> define
39   * methods such as {@code equals}, {@code hashCode} and {@code
40   * compareTo} because instances are expected to be mutated, and so are
41   * not useful as collection keys.
42   *
43   * <p><em>jsr166e note: This class is targeted to be placed in
44   * java.util.concurrent.atomic.</em>
45   *
46   * @since 1.8
47   * @author Doug Lea
48   */
49  @GwtCompatible(emulated = true)
50  final class LongAdder extends Striped64 implements Serializable, LongAddable {
51      private static final long serialVersionUID = 7249069246863182397L;
52  
53      /**
54       * Version of plus for use in retryUpdate
55       */
56      final long fn(long v, long x) { return v + x; }
57  
58      /**
59       * Creates a new adder with initial sum of zero.
60       */
61      public LongAdder() {
62      }
63  
64      /**
65       * Adds the given value.
66       *
67       * @param x the value to add
68       */
69      public void add(long x) {
70          Cell[] as; long b, v; int[] hc; Cell a; int n;
71          if ((as = cells) != null || !casBase(b = base, b + x)) {
72              boolean uncontended = true;
73              if ((hc = threadHashCode.get()) == null ||
74                  as == null || (n = as.length) < 1 ||
75                  (a = as[(n - 1) & hc[0]]) == null ||
76                  !(uncontended = a.cas(v = a.value, v + x)))
77                  retryUpdate(x, hc, uncontended);
78          }
79      }
80  
81      /**
82       * Equivalent to {@code add(1)}.
83       */
84      public void increment() {
85          add(1L);
86      }
87  
88      /**
89       * Equivalent to {@code add(-1)}.
90       */
91      public void decrement() {
92          add(-1L);
93      }
94  
95      /**
96       * Returns the current sum.  The returned value is <em>NOT</em> an
97       * atomic snapshot; invocation in the absence of concurrent
98       * updates returns an accurate result, but concurrent updates that
99       * occur while the sum is being calculated might not be
100      * incorporated.
101      *
102      * @return the sum
103      */
104     public long sum() {
105         long sum = base;
106         Cell[] as = cells;
107         if (as != null) {
108             int n = as.length;
109             for (int i = 0; i < n; ++i) {
110                 Cell a = as[i];
111                 if (a != null)
112                     sum += a.value;
113             }
114         }
115         return sum;
116     }
117 
118     /**
119      * Resets variables maintaining the sum to zero.  This method may
120      * be a useful alternative to creating a new adder, but is only
121      * effective if there are no concurrent updates.  Because this
122      * method is intrinsically racy, it should only be used when it is
123      * known that no threads are concurrently updating.
124      */
125     public void reset() {
126         internalReset(0L);
127     }
128 
129     /**
130      * Equivalent in effect to {@link #sum} followed by {@link
131      * #reset}. This method may apply for example during quiescent
132      * points between multithreaded computations.  If there are
133      * updates concurrent with this method, the returned value is
134      * <em>not</em> guaranteed to be the final value occurring before
135      * the reset.
136      *
137      * @return the sum
138      */
139     public long sumThenReset() {
140         long sum = base;
141         Cell[] as = cells;
142         base = 0L;
143         if (as != null) {
144             int n = as.length;
145             for (int i = 0; i < n; ++i) {
146                 Cell a = as[i];
147                 if (a != null) {
148                     sum += a.value;
149                     a.value = 0L;
150                 }
151             }
152         }
153         return sum;
154     }
155 
156     /**
157      * Returns the String representation of the {@link #sum}.
158      * @return the String representation of the {@link #sum}
159      */
160     public String toString() {
161         return Long.toString(sum());
162     }
163 
164     /**
165      * Equivalent to {@link #sum}.
166      *
167      * @return the sum
168      */
169     public long longValue() {
170         return sum();
171     }
172 
173     /**
174      * Returns the {@link #sum} as an {@code int} after a narrowing
175      * primitive conversion.
176      */
177     public int intValue() {
178         return (int)sum();
179     }
180 
181     /**
182      * Returns the {@link #sum} as a {@code float}
183      * after a widening primitive conversion.
184      */
185     public float floatValue() {
186         return (float)sum();
187     }
188 
189     /**
190      * Returns the {@link #sum} as a {@code double} after a widening
191      * primitive conversion.
192      */
193     public double doubleValue() {
194         return (double)sum();
195     }
196 
197     private void writeObject(ObjectOutputStream s) throws IOException {
198         s.defaultWriteObject();
199         s.writeLong(sum());
200     }
201 
202     private void readObject(ObjectInputStream s)
203             throws IOException, ClassNotFoundException {
204         s.defaultReadObject();
205         busy = 0;
206         cells = null;
207         base = s.readLong();
208     }
209 
210 }